
package com.shiro.test.service.impl;

import com.auth0.jwt.exceptions.TokenExpiredException;
import com.shiro.sdk.properties.JwtProperties;
import com.shiro.sdk.realm.JwtAuthorizingRealm;
import com.shiro.sdk.utils.JwtUtil;
import com.shiro.test.entity.User;
import com.shiro.test.service.ShiroService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashSet;


/**
 * Shiro-权限相关的业务处理
 */
@Slf4j
@Service
public class ShiroServiceImpl extends JwtAuthorizingRealm implements ShiroService {

    @Resource
    private JwtProperties jwtProperties;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        if (log.isDebugEnabled()) {
            log.debug("进入授权 doGetAuthorizationInfo");
            log.debug("the toke is  {}", principals.toString());
            log.debug("realmName = {}", getName());
        }

        // 该用户具有哪些权限,这里需要从数据库查数据，为了测试方便造了条数据
        String username = new JwtUtil(jwtProperties).getUsername(principals.toString());
        //HashSet<String> permissionsSet = permissionService.get(username)

        HashSet<String> permissionsSet = new HashSet();
        permissionsSet.add("edit");
        authorizationInfo.addStringPermissions(permissionsSet);

        // 该用户具有哪些角色,这里需要从数据库查数据，为了测试方便造了条数据
        //HashSet<String> roleSet = roleService.get(username)
        HashSet<String> roleSet = new HashSet();
        roleSet.add("admin");
        authorizationInfo.addRoles(roleSet);

        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) {
        String token = (String) auth.getCredentials();
        // 解密获得username，用于和数据库进行对比
        String username = new JwtUtil(jwtProperties).getUsername(token);

        if (username == null) {
            throw new AuthenticationException("token invalid");
        }

        //这里需要从数据库查出用户,为了测试方便所以造了条数据
        //User userBean = userService.getUser(username);
        User userBean = new User();
        userBean.setUserName("zhangsan");
        userBean.setPassword("123456");
        if (userBean == null) {
            throw new AuthenticationException("User didn't existed!");
        }
        boolean checkTokenResult = false;
        try {
            checkTokenResult = new JwtUtil(jwtProperties).verify(token, username, userBean.getPassword());
        }catch (TokenExpiredException e){
            throw new UnauthenticatedException("token 已失效");
        }catch (Exception e){
            throw e;
        }
        if (! checkTokenResult) {
            throw new AuthenticationException("Username or password error");
        }
        return new SimpleAuthenticationInfo(token, token, "jwtAuthorizingRealm");
    }
}
